package com.kexio.core.security.context;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 用户上下文信息
 *
 * @author Kexio Team
 * @since 1.0.0
 */
public class UserContext implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 用户ID
     */
    private Long userId;

    /**
     * 用户名
     */
    private String username;

    /**
     * 用户昵称
     */
    private String nickname;

    /**
     * 用户邮箱
     */
    private String email;

    /**
     * 手机号
     */
    private String phone;

    /**
     * 头像地址
     */
    private String avatar;

    /**
     * 租户ID
     */
    private Long tenantId;

    /**
     * 租户名称
     */
    private String tenantName;

    /**
     * 部门ID
     */
    private Long deptId;

    /**
     * 部门名称
     */
    private String deptName;

    /**
     * 角色列表
     */
    private List<String> roles = new ArrayList<>();

    /**
     * 权限列表
     */
    private List<String> permissions = new ArrayList<>();

    /**
     * 登录时间
     */
    private LocalDateTime loginTime;

    /**
     * 登录IP
     */
    private String loginIp;

    /**
     * 会话ID
     */
    private String sessionId;

    /**
     * 是否为超级管理员
     */
    private Boolean isAdmin;

    /**
     * 扩展属性
     */
    private Set<String> attributes = new HashSet<>();

    // 默认构造函数
    public UserContext() {
    }

    // Builder构造函数
    private UserContext(Builder builder) {
        this.userId = builder.userId;
        this.username = builder.username;
        this.nickname = builder.nickname;
        this.email = builder.email;
        this.phone = builder.phone;
        this.avatar = builder.avatar;
        this.tenantId = builder.tenantId;
        this.tenantName = builder.tenantName;
        this.deptId = builder.deptId;
        this.deptName = builder.deptName;
        this.roles = builder.roles;
        this.permissions = builder.permissions;
        this.loginTime = builder.loginTime;
        this.loginIp = builder.loginIp;
        this.sessionId = builder.sessionId;
        this.isAdmin = builder.isAdmin;
        this.attributes = builder.attributes;
    }

    /**
     * 检查用户是否拥有指定角色
     *
     * @param role 角色
     * @return 是否拥有
     */
    public boolean hasRole(String role) {
        return roles != null && roles.contains(role);
    }

    /**
     * 检查用户是否拥有任意指定角色
     *
     * @param roles 角色列表
     * @return 是否拥有任意一个
     */
    public boolean hasAnyRole(String... roles) {
        if (this.roles == null || roles == null) {
            return false;
        }
        for (String role : roles) {
            if (this.roles.contains(role)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检查用户是否拥有指定权限
     *
     * @param permission 权限
     * @return 是否拥有
     */
    public boolean hasPermission(String permission) {
        return permissions != null && permissions.contains(permission);
    }

    /**
     * 检查用户是否拥有任意指定权限
     *
     * @param permissions 权限列表
     * @return 是否拥有任意一个
     */
    public boolean hasAnyPermission(String... permissions) {
        if (this.permissions == null || permissions == null) {
            return false;
        }
        for (String permission : permissions) {
            if (this.permissions.contains(permission)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检查用户是否拥有全部指定权限
     *
     * @param permissions 权限列表
     * @return 是否拥有全部
     */
    public boolean hasAllPermissions(String... permissions) {
        if (this.permissions == null || permissions == null) {
            return false;
        }
        for (String permission : permissions) {
            if (!this.permissions.contains(permission)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 检查是否为超级管理员
     *
     * @return 是否为超级管理员
     */
    public boolean isAdmin() {
        return Boolean.TRUE.equals(isAdmin) || hasRole("admin") || hasRole("ADMIN");
    }

    /**
     * 创建Builder
     *
     * @return Builder
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * Builder类
     */
    public static class Builder {
        private Long userId;
        private String username;
        private String nickname;
        private String email;
        private String phone;
        private String avatar;
        private Long tenantId;
        private String tenantName;
        private Long deptId;
        private String deptName;
        private List<String> roles = new ArrayList<>();
        private List<String> permissions = new ArrayList<>();
        private LocalDateTime loginTime;
        private String loginIp;
        private String sessionId;
        private Boolean isAdmin;
        private Set<String> attributes = new HashSet<>();

        public Builder userId(Long userId) {
            this.userId = userId;
            return this;
        }

        public Builder username(String username) {
            this.username = username;
            return this;
        }

        public Builder nickname(String nickname) {
            this.nickname = nickname;
            return this;
        }

        public Builder email(String email) {
            this.email = email;
            return this;
        }

        public Builder phone(String phone) {
            this.phone = phone;
            return this;
        }

        public Builder avatar(String avatar) {
            this.avatar = avatar;
            return this;
        }

        public Builder tenantId(Long tenantId) {
            this.tenantId = tenantId;
            return this;
        }

        public Builder tenantName(String tenantName) {
            this.tenantName = tenantName;
            return this;
        }

        public Builder deptId(Long deptId) {
            this.deptId = deptId;
            return this;
        }

        public Builder deptName(String deptName) {
            this.deptName = deptName;
            return this;
        }

        public Builder roles(List<String> roles) {
            this.roles = roles != null ? roles : new ArrayList<>();
            return this;
        }

        public Builder permissions(List<String> permissions) {
            this.permissions = permissions != null ? permissions : new ArrayList<>();
            return this;
        }

        public Builder loginTime(LocalDateTime loginTime) {
            this.loginTime = loginTime;
            return this;
        }

        public Builder loginIp(String loginIp) {
            this.loginIp = loginIp;
            return this;
        }

        public Builder sessionId(String sessionId) {
            this.sessionId = sessionId;
            return this;
        }

        public Builder isAdmin(Boolean isAdmin) {
            this.isAdmin = isAdmin;
            return this;
        }

        public Builder attributes(Set<String> attributes) {
            this.attributes = attributes != null ? attributes : new HashSet<>();
            return this;
        }

        public UserContext build() {
            return new UserContext(this);
        }
    }

    // Getter和Setter方法
    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public Long getTenantId() {
        return tenantId;
    }

    public void setTenantId(Long tenantId) {
        this.tenantId = tenantId;
    }

    public String getTenantName() {
        return tenantName;
    }

    public void setTenantName(String tenantName) {
        this.tenantName = tenantName;
    }

    public Long getDeptId() {
        return deptId;
    }

    public void setDeptId(Long deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public List<String> getRoles() {
        return roles;
    }

    public void setRoles(List<String> roles) {
        this.roles = roles;
    }

    public List<String> getPermissions() {
        return permissions;
    }

    public void setPermissions(List<String> permissions) {
        this.permissions = permissions;
    }

    public LocalDateTime getLoginTime() {
        return loginTime;
    }

    public void setLoginTime(LocalDateTime loginTime) {
        this.loginTime = loginTime;
    }

    public String getLoginIp() {
        return loginIp;
    }

    public void setLoginIp(String loginIp) {
        this.loginIp = loginIp;
    }

    public String getSessionId() {
        return sessionId;
    }

    public void setSessionId(String sessionId) {
        this.sessionId = sessionId;
    }

    public Boolean getIsAdmin() {
        return isAdmin;
    }

    public void setIsAdmin(Boolean isAdmin) {
        this.isAdmin = isAdmin;
    }

    public Set<String> getAttributes() {
        return attributes;
    }

    public void setAttributes(Set<String> attributes) {
        this.attributes = attributes;
    }

    @Override
    public String toString() {
        return "UserContext{" +
                "userId=" + userId +
                ", username='" + username + '\'' +
                ", nickname='" + nickname + '\'' +
                ", tenantId=" + tenantId +
                ", roles=" + roles +
                ", permissions=" + permissions +
                '}';
    }
}
